package com.xyz.app.config;

import com.github.pagehelper.PageInterceptor;
import com.xyz.app.properties.MybatisProperties;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.boot.autoconfigure.SpringBootVFS;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.ResourceLoader;
import org.springframework.util.StringUtils;
import tk.mybatis.orderbyhelper.OrderByHelper;

import javax.annotation.PostConstruct;
import javax.sql.DataSource;
import java.util.Properties;

/**
 * <p>
 * 功能概述:
 * </p>
 * <p>
 * 功能详述:
 * </p>
 */
@Configuration
@ConditionalOnClass({ SqlSessionFactory.class, SqlSessionFactoryBean.class })
@AutoConfigureAfter(DataSourceConfig.class)
public class MybatisAutoConfiguration {
    /*========================================================================*
     *                         Public Fields (公共属性)
     *========================================================================*/

    /*========================================================================*
     *                         Private Fields (私有属性)
     *========================================================================*/

    @Autowired
    private DataSource dataSource;

    @Autowired
    private MybatisProperties mybatisProperties;

    @Autowired(required = false)
    private Interceptor[] interceptors;

    @Autowired
    private ResourceLoader resourceLoader = new DefaultResourceLoader();

    /*========================================================================*
     *                         Construct Methods (构造方法)
     *========================================================================*/

    /*========================================================================*
     *                         Public Methods (公有方法)
     *========================================================================*/

    /*
    @Bean
    public MybatisRedisCache mybatisRedisCache()
    {
        MybatisRedisCache chache = new MybatisRedisCache(DB_REDIS_KEY);
        return chache;
    }

    @Bean(name = "sqlSessionFactory")
    @ConditionalOnMissingBean
    public SqlSessionFactory sqlSessionFactory(DataSource dataSource,MybatisRedisCache mybatisRedisCache) throws Exception {
        SqlSessionFactoryBean factory = new SqlSessionFactoryBean();
        factory.setDataSource(dataSource);
        //factory.setCache(mybatisRedisCache);
        if (StringUtils.hasText(this.mybatisProperties.getConfig())) {
            factory.setConfigLocation(
                    this.resourceLoader.getResource(this.mybatisProperties.getConfig()));
        } else {
            if (this.interceptors != null && this.interceptors.length > 0) {
                factory.setPlugins(this.interceptors);
            }
            org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
            configuration.setLogPrefix("dao.");
            configuration.setLogImpl(org.apache.ibatis.logging.stdout.StdOutImpl.class);
            factory.setConfiguration(configuration);
            factory.setTypeAliasesPackage(this.mybatisProperties.getTypeAliasesPackage());
            factory.setTypeHandlersPackage(this.mybatisProperties.getTypeHandlersPackage());
            factory.setMapperLocations(this.mybatisProperties.getMapperLocations());
        }
        return factory.getObject();
    }
    */

    @Bean(name = "sqlSessionFactory")
    @ConditionalOnMissingBean
    public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
        SqlSessionFactoryBean factory = new SqlSessionFactoryBean();
        factory.setDataSource(dataSource);
        if (StringUtils.hasText(this.mybatisProperties.getConfig())) {
            factory.setConfigLocation(
                    this.resourceLoader.getResource(this.mybatisProperties.getConfig()));
        } else {
            if (this.interceptors != null && this.interceptors.length > 0) {
                factory.setPlugins(this.interceptors);
            }
            org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
            configuration.setLogPrefix("dao.");
            configuration.setLogImpl(org.apache.ibatis.logging.stdout.StdOutImpl.class);


            factory.setConfiguration(configuration);
//            factory.setTypeAliasesPackage(this.mybatisProperties.getTypeAliasesPackage());
//            factory.setTypeHandlersPackage(this.mybatisProperties.getTypeHandlersPackage());
            factory.setMapperLocations(this.mybatisProperties.getMapperLocations());
            factory.setVfs(SpringBootVFS.class);
        }
        return factory.getObject();
    }

    @Bean
    @ConditionalOnMissingBean
    public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory,
                this.mybatisProperties.getExecutorType());
    }

    @PostConstruct
    public void init(){
        this.interceptors = new Interceptor[2];
        interceptors[1] = orderByInterceptor();
        interceptors[0] = pageInterceptor();
    }

    /*========================================================================*
     *                         Private Methods (私有方法)
     *========================================================================*/
    private OrderByHelper orderByInterceptor(){
        OrderByHelper interceptor = new OrderByHelper();
        return interceptor;
    }

    private PageInterceptor pageInterceptor()
    {
        PageInterceptor pageInterceptor = new PageInterceptor();
        Properties p = new Properties();
        p.setProperty("reasonable", "false");
        p.setProperty("helperDialect", "mysql");
        p.setProperty("supportMethodsArguments", "true");
        p.setProperty("reasonable", "true");
        p.setProperty("params", "count=countSql");
        p.setProperty("autoRuntimeDialect", "true");
        pageInterceptor.setProperties(p);
        return pageInterceptor;
    }

    /*========================================================================*
     *                         Private Methods (私有方法)
     *========================================================================*/
}
